﻿// Learn more about F# at http://fsharp.net
#nowarn "40"
#nowarn "62"

open System
open System.IO
open System.Net
open System.Text
open Microsoft.FSharp.Collections
open Spread

type ConsumerState = {
    GroupName   : string
    Channel     : SpreadMessage -> unit
}

let private handleMessage state msg =
    match msg.MessageType with 
    | 1us ->
        let br = new BinaryReader(new MemoryStream(msg.Data), Encoding.ASCII)
        let value = br.ReadInt32()
        printfn "%s: %d" msg.Sender value
    | _ -> ()
    Some state

let private processEvent state msg = 
    match msg with
    | Connection (group, chan) ->
        Console.Title <- group
        let ms = new MemoryStream()
        let bw = new BinaryWriter(ms, Encoding.ASCII)
        group |> bw.Write
        Data { 
            Groups = [|"Provider"|]; 
            ServiceType = MessageFlags.Causal; 
            MessageType = 2us; 
            Data = ms.ToArray() } |> chan
        Some { state with GroupName = group; Channel = chan}
    | Message msg ->
        handleMessage state msg
    | Transition _
    | MembershipChange _ ->
        Some state
    | _ ->
        None

// Spawn our agent, passing the endPoint of the spread daemon
let private startAgent endPoint = 
    let events = MailboxProcessor.Start(fun inbox ->
        let rec loop state = 
            async {
                let! msg = inbox.Receive()
                match processEvent state msg with
                | Some state' ->
                    do! loop state'
                | None -> ()
            }
        loop { GroupName = ""; Channel = ignore; })

    events.Post |> Spread.runClient endPoint true None
    events

match System.Environment.GetCommandLineArgs() with
| [|_;ipaddr;port|] ->
    let ep = IPEndPoint(IPAddress.Parse(ipaddr), Int32.of_string(port))
    let mbox = startAgent ep
    System.Console.ReadLine() |> ignore
| _ ->
    printfn "Usage: FSpreadConsumer <idaddr> <port>"